package com.tobeface.wechat.request.api;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tobeface.modules.lang.Function;
import com.tobeface.modules.lang.Langs;
import com.tobeface.modules.lang.Requires;
import com.tobeface.wechat.request.AbstractWeChatApiRequestBuilder;
import com.tobeface.wechat.request.WeChatRequest;

import java.util.List;
import java.util.Map;

/**
 * @author loudyn
 */
public class MenuApiRequestBuilder {

    public static final MenuApiRequestBuilder INSTANCE = new MenuApiRequestBuilder();

    /**
     * @return
     */
    public GetAllMenusApiRequestBuilder getAll() {
        return new GetAllMenusApiRequestBuilder();
    }

    /**
     * @return
     */
    public CleanAllMenusApiRequestBuilder cleanAll() {
        return new CleanAllMenusApiRequestBuilder();
    }

    /**
     * @return
     */
    public CreateMenuApiRequestBuilder create() {
        return new CreateMenuApiRequestBuilder();
    }

    private MenuApiRequestBuilder() {
    }

    /**
     * @author loudyn
     */
    public class GetAllMenusApiRequestBuilder extends AbstractWeChatApiRequestBuilder {

        /**
         *
         */
        GetAllMenusApiRequestBuilder() {
            super("https://api.weixin.qq.com/cgi-bin/menu/get", WeChatRequest.Verb.GET);
        }

        @Override
        protected void configRequest(WeChatRequest request) {
        }
    }

    /**
     * @author loudyn
     */
    public class CleanAllMenusApiRequestBuilder extends AbstractWeChatApiRequestBuilder {

        /**
         * @param url
         * @param verb
         */
        CleanAllMenusApiRequestBuilder() {
            // unbelievable verb !
            super("https://api.weixin.qq.com/cgi-bin/menu/delete", WeChatRequest.Verb.GET);
        }

        @Override
        protected void configRequest(WeChatRequest request) {
        }
    }

    /**
     * @author loudyn
     */
    public class CreateMenuApiRequestBuilder extends AbstractWeChatApiRequestBuilder {

        private static final int MAX_MENUS = 3;
        private List<ButtonBuilder> builders = Lists.newArrayList();

        /**
         *
         */
        CreateMenuApiRequestBuilder() {
            super("https://api.weixin.qq.com/cgi-bin/menu/create", WeChatRequest.Verb.POST);
        }

        /**
         * @return
         */
        public ButtonBuilder button() {
            if (builders.size() >= MAX_MENUS) {
                throw new UnsupportedOperationException("menus count must between [1,3]!");
            }

            ButtonBuilder builder = new ButtonBuilder(this);
            builders.add(builder);
            return builder;
        }

        @Override
        protected void configRequest(WeChatRequest request) {
            List<Map<String, Object>> menuInfos = Langs.map(builders, new Function<ButtonBuilder, Map<String, Object>>() {
                @Override
                public Map<String, Object> apply(ButtonBuilder menuBuilder) {
                    return menuBuilder.getInfos();
                }
            });
            request.entity(ImmutableMap.of("button", menuInfos));
        }

        /**
         *
         */
        public class ButtonBuilder {

            List<Map<String, Object>> buttons = Lists.newArrayList();
            Map<String, Object> props = Maps.newHashMap();
            Map<String, Object> curbutton;

            final CreateMenuApiRequestBuilder parent;

            ButtonBuilder(CreateMenuApiRequestBuilder parent) {
                this.parent = parent;
            }

            Map<String, Object> getInfos() {
                if (buttons.isEmpty()) {
                    return props;
                }

                String name = (String) props.get("name");
                return ImmutableMap.of("name", name, "sub_button", buttons);
            }

            public ButtonBuilder name(String name) {
                Requires.hasText(name, "name must not be empty or null!");
                getActivedProps().put("name", name);
                return this;
            }

            private Map<String, Object> getActivedProps() {
                return null != curbutton ? curbutton : props;
            }

            public ButtonBuilder clickType() {
                getActivedProps().put("type", "click");
                return this;
            }

            public ButtonBuilder viewType() {
                getActivedProps().put("type", "view");
                return this;
            }

            public ButtonBuilder key(String key) {
                Requires.hasText(key, "Key must not be empty or null!");
                getActivedProps().put("key", key);
                return this;
            }

            public ButtonBuilder url(String url) {
                Requires.hasText(url, "Url must not be empty or null!");
                getActivedProps().put("url", url);
                return this;
            }

            public ButtonBuilder subButton() {
                curbutton = Maps.newHashMap();
                buttons.add(curbutton);
                return this;
            }

            public ButtonBuilder button() {
                return parent.button();
            }

            /**
             * @return
             */
            public WeChatRequest build() {
                return parent.build();
            }
        }
    }
}
